home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / stevie.arc / EDIT.C < prev    next >
Text File  |  1990-01-10  |  7KB  |  349 lines

  1. /*
  2.  * STevie - ST editor for VI enthusiasts.     ...Tim Thompson...twitch!tjt...
  3.  *
  4.  * Extensive modifications by:  Tony Andrews       onecom!wldrdg!tony
  5.  * Turbo C 1.5 port by: Denny Muscatelli 061988
  6.  */
  7.  
  8. #include "stevie.h"
  9.  
  10. /*
  11.  * This flag is used to make auto-indent work right on lines where only
  12.  * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  13.  * and reset when any other editting is done on the line. If an <ESC>
  14.  * or <RETURN> is received, and did_ai is TRUE, the line is truncated.
  15.  */
  16. bool_t    did_ai = FALSE;
  17.  
  18. void
  19. edit()
  20. {
  21.     int c;
  22.     char *p, *q;
  23.  
  24.     Prenum = 0;
  25.  
  26.     /* position the display and the cursor at the top of the file. */
  27.     *Topchar = *Filemem;
  28.     *Curschar = *Filemem;
  29.     Cursrow = Curscol = 0;
  30.  
  31.     for ( ;; ) {
  32.  
  33.     /* Figure out where the cursor is based on Curschar. */
  34.     cursupdate();
  35.  
  36.     windgoto(Cursrow,Curscol);
  37.  
  38.     c = vgetc();
  39.  
  40.     if (State == NORMAL) {
  41.  
  42.         /* We're in the normal (non-insert) mode. */
  43.  
  44.         /* Pick up any leading digits and compute 'Prenum' */
  45.         if ( (Prenum>0 && isdigit(c)) || (isdigit(c) && c!='0') ){
  46.             Prenum = Prenum*10 + (c-'0');
  47.             continue;
  48.         }
  49.         /* execute the command */
  50.         normal(c);
  51.         Prenum = 0;
  52.  
  53.     } else {
  54.  
  55.         switch (c) {    /* We're in insert mode */
  56.  
  57.         case ESC:    /* an escape ends input mode */
  58.  
  59.             set_want_col = TRUE;
  60.  
  61.             /* Don't end up on a '\n' if you can help it. */
  62.             if (gchar(Curschar) == NUL && Curschar->index != 0)
  63.                 dec(Curschar);
  64.  
  65.             /*
  66.              * The cursor should end up on the last inserted
  67.              * character. This is an attempt to match the real
  68.              * 'vi', but it may not be quite right yet.
  69.              */
  70.             if (Curschar->index != 0 && !endofline(Curschar))
  71.                 dec(Curschar);
  72.  
  73.             State = NORMAL;
  74.             msg("");
  75.             *Uncurschar = *Insstart;
  76.             Undelchars = Ninsert;
  77.             /* Undobuff[0] = '\0'; */
  78.             /* construct the Redo buffer */
  79.             p=Redobuff;
  80.             q=Insbuff;
  81.             while ( q < Insptr )
  82.                 *p++ = *q++;
  83.             *p++ = ESC;
  84.             *p = NUL;
  85.             updatescreen();
  86.             break;
  87.  
  88.         case CTRL('D'):
  89.             /*
  90.              * Control-D is treated as a backspace in insert
  91.              * mode to make auto-indent easier. This isn't
  92.              * completely compatible with vi, but it's a lot
  93.              * easier than doing it exactly right, and the
  94.              * difference isn't very noticeable.
  95.              */
  96.         case BS:
  97.             /* can't backup past starting point */
  98.             if (Curschar->linep == Insstart->linep &&
  99.                 Curschar->index <= Insstart->index) {
  100.                 beep();
  101.                 break;
  102.             }
  103.  
  104.             /* can't backup to a previous line */
  105.             if (Curschar->linep != Insstart->linep &&
  106.                 Curschar->index <= 0) {
  107.                 beep();
  108.                 break;
  109.             }
  110.  
  111.             did_ai = FALSE;
  112.             dec(Curschar);
  113.             delchar(TRUE);
  114.             Insptr--;
  115.             Ninsert--;
  116.             cursupdate();
  117.             updateline();
  118.             break;
  119.  
  120.         case CR:
  121.         case NL:
  122.             *Insptr++ = NL;
  123.             Ninsert++;
  124.             opencmd(FORWARD, TRUE);        /* open a new line */
  125.             cursupdate();
  126.             updatescreen();
  127.             break;
  128.  
  129.         default:
  130.             did_ai = FALSE;
  131.             insertchar(c);
  132.             break;
  133.         }
  134.     }
  135.     }
  136. }
  137.  
  138. /*
  139.  * Special characters in this context are those that need processing other
  140.  * than the simple insertion that can be performed here. This includes ESC
  141.  * which terminates the insert, and CR/NL which need special processing to
  142.  * open up a new line. This routine tries to optimize insertions performed
  143.  * by the "redo" command, so it needs to know when it should stop and defer
  144.  * processing to the "normal" mechanism.
  145.  */
  146. #define    ISSPECIAL(c)    ((c) == NL || (c) == CR || (c) == ESC)
  147.  
  148. void
  149. insertchar(c)
  150. int c;
  151. {
  152.     char *p;
  153.  
  154.     if ( ! anyinput() ) {
  155.         inschar(c);
  156.         *Insptr++ = c;
  157.         Ninsert++;
  158.         /*
  159.          * The following kludge avoids overflowing the statically
  160.          * allocated insert buffer. Just dump the user back into
  161.          * command mode, and print a message.
  162.          */
  163.         if (Insptr+10 >= &Insbuff[1024]) {
  164.             stuffin(mkstr(ESC));
  165.             emsg("No buffer space - returning to command mode");
  166.  
  167. /* added for turbo c port 6-14-88 dlm */
  168.  
  169. #ifdef TURBO
  170.             msleep(2);
  171. #else
  172.                         sleep(2);
  173. #endif
  174.         }
  175.     }
  176.     else {
  177.         /* If there's any pending input, grab it all at once. */
  178.         p = Insptr;
  179.         *Insptr++ = c;
  180.         Ninsert++;
  181.         for (c = vpeekc(); !ISSPECIAL(c) ;c = vpeekc()) {
  182.             c = vgetc();
  183.             *Insptr++ = c;
  184.             Ninsert++;
  185.         }
  186.         *Insptr = '\0';
  187.         insstr(p);
  188.     }
  189.     updateline();
  190. }
  191.  
  192. void
  193. getout()
  194. {
  195.     windgoto(Rows-1,0);
  196.     putchar('\r');
  197.     putchar('\n');
  198.     windexit(0);
  199. }
  200.  
  201. void
  202. scrolldown(nlines)
  203. int nlines;
  204. {
  205.     register LPTR    *p;
  206.     register int    done = 0;    /* total # of physical lines done */
  207.  
  208.     /* Scroll up 'nlines' lines. */
  209.     while (nlines--) {
  210.         if ((p = prevline(Topchar)) == NULL)
  211.             break;
  212.         done += plines(p);
  213.         *Topchar = *p;
  214.         if (Curschar->linep == Botchar->linep->prev)
  215.             *Curschar = *prevline(Curschar);
  216.     }
  217.     s_ins(0, done);
  218. }
  219.  
  220. void
  221. scrollup(nlines)
  222. int nlines;
  223. {
  224.     register LPTR    *p;
  225.     register int    done = 0;    /* total # of physical lines done */
  226.     register int    pl;        /* # of plines for the current line */
  227.  
  228.     /* Scroll down 'nlines' lines. */
  229.     while (nlines--) {
  230.         pl = plines(Topchar);
  231.         if ((p = nextline(Topchar)) == NULL)
  232.             break;
  233.         done += pl;
  234.         if (Curschar->linep == Topchar->linep)
  235.             *Curschar = *p;
  236.         *Topchar = *p;
  237.  
  238.     }
  239.     s_del(0, done);
  240. }
  241.  
  242. /*
  243.  * oneright
  244.  * oneleft
  245.  * onedown
  246.  * oneup
  247.  *
  248.  * Move one char {right,left,down,up}.  Return TRUE when
  249.  * sucessful, FALSE when we hit a boundary (of a line, or the file).
  250.  */
  251.  
  252. bool_t
  253. oneright()
  254. {
  255.     set_want_col = TRUE;
  256.  
  257.     switch (inc(Curschar)) {
  258.  
  259.     case 0:
  260.         return TRUE;
  261.  
  262.     case 1:
  263.         dec(Curschar);        /* crossed a line, so back up */
  264.         /* fall through */
  265.     case -1:
  266.         return FALSE;
  267.     }
  268. }
  269.  
  270. bool_t
  271. oneleft()
  272. {
  273.     set_want_col = TRUE;
  274.  
  275.     switch (dec(Curschar)) {
  276.  
  277.     case 0:
  278.         return TRUE;
  279.  
  280.     case 1:
  281.         inc(Curschar);        /* crossed a line, so back up */
  282.         /* fall through */
  283.     case -1:
  284.         return FALSE;
  285.     }
  286. }
  287.  
  288. void
  289. beginline(flag)
  290. bool_t    flag;
  291. {
  292.     while ( oneleft() )
  293.         ;
  294.     if (flag) {
  295.         while (isspace(gchar(Curschar)) && oneright())
  296.             ;
  297.     }
  298.     set_want_col = TRUE;
  299. }
  300.  
  301. bool_t
  302. oneup(n)
  303. {
  304.     LPTR p, *np;
  305.     int k;
  306.  
  307.     p = *Curschar;
  308.     for ( k=0; k<n; k++ ) {
  309.         /* Look for the previous line */
  310.         if ( (np=prevline(&p)) == NULL ) {
  311.             /* If we've at least backed up a little .. */
  312.             if ( k > 0 )
  313.                 break;    /* to update the cursor, etc. */
  314.             else
  315.                 return FALSE;
  316.         }
  317.         p = *np;
  318.     }
  319.     *Curschar = p;
  320.     /* This makes sure Topchar gets updated so the complete line */
  321.     /* is one the screen. */
  322.     cursupdate();
  323.     /* try to advance to the column we want to be at */
  324.     *Curschar = *coladvance(&p, Curswant);
  325.     return TRUE;
  326. }
  327.  
  328. bool_t
  329. onedown(n)
  330. {
  331.     LPTR p, *np;
  332.     int k;
  333.  
  334.     p = *Curschar;
  335.     for ( k=0; k<n; k++ ) {
  336.         /* Look for the next line */
  337.         if ( (np=nextline(&p)) == NULL ) {
  338.             if ( k > 0 )
  339.                 break;
  340.             else
  341.                 return FALSE;
  342.         }
  343.         p = *np;
  344.     }
  345.     /* try to advance to the column we want to be at */
  346.     *Curschar = *coladvance(&p, Curswant);
  347.     return TRUE;
  348. }
  349.